/**
 * 
 */
package com.security.frame.core.code.image;

import com.security.frame.core.code.ValidateCodeGenerator;
import com.security.frame.core.enums.ImgCodeType;
import com.security.frame.core.properties.SecurityProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.UnsupportedEncodingException;
import java.util.Random;

/**
 * 图形验证码生成器
 *
 * @author wangjie
 * @version V1.0
 * @date 2019/11/6
 */
@Slf4j
public class ImageCodeGenerator implements ValidateCodeGenerator {

	private static char[] codeSequence = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R','S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
	/**
	 * 系统配置
	 */
	@Autowired
	private SecurityProperties securityProperties;
	

	@Override
	public ImageCode generate(ServletWebRequest request) {
		int width = ServletRequestUtils.getIntParameter(request.getRequest(), "width",
				securityProperties.getCode().getImage().getWidth());
		int height = ServletRequestUtils.getIntParameter(request.getRequest(), "height",
				securityProperties.getCode().getImage().getHeight());
		int codeCount = securityProperties.getCode().getImage().getLength();

		int lineCount = securityProperties.getCode().getImage().getLineCount();

		ImgCodeType imgCodeType = securityProperties.getCode().getImage().getImgCodeType();

        return createCode(width, height, codeCount, lineCount, imgCodeType);
	}

	public ImageCode createCode(int width, int height, int codeCount, int lineCount,ImgCodeType imgCodeType) {

		int x = width / (codeCount + 2);
		int fontHeight = height - 2;
		int codeY = height - 4;

		// 图像buffer
		BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		Graphics2D g = buffImg.createGraphics();
		// 将图像填充为白色
		g.setColor(Color.WHITE);
		g.fillRect(0, 0, width, height);
		// 创建字体
		Font font=new Font("微软雅黑",Font.PLAIN, fontHeight);
		g.setFont(font);
		drawRandomLine(width,height,g,lineCount);
		// randomCode记录随机产生的验证码
		StringBuffer randomCode = new StringBuffer();
		// 随机产生codeCount个字符的验证码。
		for (int i = 0; i < codeCount; i++) {
			String strRand = getRandomStr(imgCodeType);
			// 产生随机的颜色值，让输出的每个字符的颜色值都将不同。
			g.setColor(getRandomColor());
			g.drawString(strRand, (i + 1) * x, codeY);
			// 将产生的四个随机数组合在一起。
			randomCode.append(strRand);
		}
		return new ImageCode(buffImg, randomCode.toString(), securityProperties.getCode().getImage().getExpireIn());
	}

	private String getRandomStr(ImgCodeType type) {
		switch (type) {
			case ENANDNUMBER:
				return creatENAndNumberCode();
			case HAN:
				return creatHan();
			case EN:
				return creatENCode();
			case NUMBER:
				return creatNumberCode();
			default:
				return creatENAndNumberCode();
		}
	}

	/**
	 * 单个汉字
	 *
	 * @return
	 */
	public static String creatHan() {
		String code = "";
		Random random = new Random();
		//一个汉字两个字节
		byte[] bytes = new byte[2];
		bytes[0] = Integer.valueOf(176 + Math.abs(random.nextInt(39))).byteValue();
		bytes[1] = Integer.valueOf(161 + Math.abs(random.nextInt(93))).byteValue();
		try {
			code = new String(bytes, "GBK");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return code;
	}

	/**
	 * 英文字母加数字
	 *
	 * @return
	 */
	public static String creatENAndNumberCode() {
		Random random = new Random();
		return String.valueOf(codeSequence[random.nextInt(codeSequence.length)]);
	}

	/**
	 * 英文字母
	 *
	 *
	 * @return
	 */
	public static String creatENCode() {
		StringBuffer code = new StringBuffer();
		Random random = new Random();
		int s = random.nextInt(25) + 65;
		code.append((char) s);
		return code.toString();
	}


	/**
	 * 纯数字验证码
	 *
	 *
	 * @return
	 */
	public static String creatNumberCode() {
		StringBuffer code = new StringBuffer();
		Random random = new Random();
		return code.append(random.nextInt(9) + "").toString();
	}


	private void drawRandomLine(int width, int height,Graphics g,int lineCount) {
		//干扰线
		for (int i = 0; i < lineCount; i++) {
			int xs = new Random().nextInt(width);
			int ys = new Random().nextInt(height);
			int xe = xs + new Random().nextInt(width / 8);
			int ye = ys + new Random().nextInt(height / 8);
			g.setColor(getRandomColor());
			g.drawLine(xs, ys, xe, ye);
		}
	}
	public Color getRandomColor(){
		int red = 0, green = 0, blue = 0;
		Random random = new Random();
		red = random.nextInt(255);
		green = random.nextInt(255);
		blue = random.nextInt(255);
		return new Color(red,green,blue);
	}
	

	public SecurityProperties getSecurityProperties() {
		return securityProperties;
	}

	public void setSecurityProperties(SecurityProperties securityProperties) {
		this.securityProperties = securityProperties;
	}
	
	

}
